package cc.rengu.igas.channel.upqc.core.service.trans;

import cc.rengu.igas.channel.upqc.common.constant.UpqcParamConstant;
import cc.rengu.igas.channel.upqc.common.constant.UpqcTreeNodeConstant;
import cc.rengu.igas.channel.upqc.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.upqc.common.util.UpqcSecurityUtil;
import cc.rengu.igas.channel.upqc.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.upqc.core.service.base.NoticeService;
import cc.rengu.igas.channel.upqc.facade.request.QrCodePayNoticeRequest;
import cc.rengu.igas.channel.upqc.facade.response.QrCodePayNoticeResponse;
import cc.rengu.igas.share.facade.request.UpqcPayResultNoticeRequest;
import cc.rengu.igas.share.facade.response.UpqcPayResultNoticeResponse;
import cc.rengu.igas.share.facade.result.Result;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.CertInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.CertInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.CertInfo;
import cc.rengu.oltp.service.common.entity.SecPlanInfo;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.cache.UnifiedCache;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.codec.binary.Base64;

import java.security.interfaces.RSAPrivateKey;
import java.util.List;
import java.util.Optional;

/**
 * 银联二维码收款交易结果通知服务
 */
public class QrCodePayNoticeService extends NoticeService {

    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        CertInfo encryptCertInfo;
        String payerInfo;
        QrCodePayNoticeRequest qrCodePayNoticeRequest = new QrCodePayNoticeRequest();
        ConvertUtil.convertOutput(qrCodePayNoticeRequest);
        //解密付款方信息
        String encoding = UpqcParamConstant.UTF_8_ENCODING;
        /* 获取敏感信息解密证书 */
        String secPlanInfoListString = xmlTreeUtil.getXmlTreeStringValue(UpqcTreeNodeConstant.SEC_PLAN_INFO_LIST);
        List<SecPlanInfo> secPlanInfoList = JSONArray.parseArray(secPlanInfoListString, SecPlanInfo.class);
        Optional<SecPlanInfo> encryptSecPlanOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(UpqcParamConstant.DECRYPT_CERT_TYPE)).findFirst();
        if (encryptSecPlanOpt.isPresent()) {
            CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
            encryptCertInfo = certInfoMapper.selectCertInfoByPrimaryKey(encryptSecPlanOpt.get().getInstId() + encryptSecPlanOpt.get().getSecPlanId() + encryptSecPlanOpt.get().getSecPlanType());
            if (encryptCertInfo == null) {
                rglog.error("根据证书索引<{}>查询证书信息失败", encryptSecPlanOpt.get().getInstId() + encryptSecPlanOpt.get().getSecPlanId() + encryptSecPlanOpt.get().getSecPlanType());
                throw new BizException(RespCodeEnum.UPQC_TRANS_ERROR.getRespCode(), RespCodeEnum.UPQC_TRANS_ERROR.getRespDesc());
            }
        } else {
            rglog.error("查询证书信息失败");
            throw new BizException(RespCodeEnum.UPQC_TRANS_ERROR.getRespCode(), RespCodeEnum.UPQC_TRANS_ERROR.getRespDesc());
        }
        if ("0".equals(encryptCertInfo.getCertSaveType())) {
            payerInfo = UpqcSecurityUtil.decryptData(qrCodePayNoticeRequest.getPayerInfoStr(), encryptCertInfo.getCertValue(), encoding);
        } else {
            /*优先从系统缓存读取*/
            RSAPrivateKey privateKey;
            String priKeyStr = (String) UnifiedCache.get(UpqcParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex());
            if (priKeyStr != null) {
                privateKey = RSAUtil.getPrivateKeyFromBase64String(priKeyStr);
            } else {
                /*从本地证书文件获取*/
                List<String> aliasList = RSAUtil.getCertAliasFromPfxCertFile(encryptCertInfo.getCertSavePath(), encryptCertInfo.getCertPassword());
                privateKey = RSAUtil.getPrivateKeyFromPfxCertFile(encryptCertInfo.getCertSavePath(), aliasList.get(0), encryptCertInfo.getCertPassword());
                if (privateKey != null) {
                    if (UnifiedCache.set(UpqcParamConstant.CERT_KEY_CACHE, encryptCertInfo.getCertIndex(), Base64.encodeBase64String(privateKey.getEncoded())) != 0) {
                        rglog.error("设置证书缓存索引号{}缓存失败", encryptCertInfo.getCertIndex());
                    }
                }
            }
            payerInfo = UpqcSecurityUtil.decryptData(qrCodePayNoticeRequest.getPayerInfoStr(), privateKey, encoding);
        }
        rglog.debug("payerInfo=[{}]", payerInfo);
        qrCodePayNoticeRequest.setPayerInfoStr(payerInfo);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.FRONT_SEQ_NUM, qrCodePayNoticeRequest.getSettleKey());
        return qrCodePayNoticeRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        QrCodePayNoticeRequest qrCodePayNoticeRequest = (QrCodePayNoticeRequest) request;
        QrCodePayNoticeResponse qrCodePayNoticeResponse = new QrCodePayNoticeResponse();

        /* 调用Share模块中的银联二维码业务公共处理服务 */
        UpqcPayResultNoticeRequest upqcPayResultNoticeRequest = new UpqcPayResultNoticeRequest();
        BeanUtil.beanCopy(qrCodePayNoticeRequest, upqcPayResultNoticeRequest);
        upqcPayResultNoticeRequest.getHeader().setTxnNum("T00SH005");
        upqcPayResultNoticeRequest.getHeader().setTraceNo(ChannelEnum.UPQC.getChannelType() + DateUtil.getCurrentDateTime("yyyyMMddHHmmssSSS") + RandomUtil.randomNumStr(10));
        DubboService dubboService = new DubboServiceImpl();
        Result<UpqcPayResultNoticeResponse> callResult = (Result<UpqcPayResultNoticeResponse>) dubboService.callDubboService("upqcUnifiedService", "payNotice", upqcPayResultNoticeRequest);
        if (null != callResult) {
            UpqcPayResultNoticeResponse upqcPayResultNoticeResponse = callResult.getResult();
            BeanUtil.beanCopy(upqcPayResultNoticeResponse, qrCodePayNoticeResponse);
        }

        /* 组装应答报文 */
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        chnlBizResponse.setResult(qrCodePayNoticeResponse);
        return chnlBizResponse;
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        QrCodePayNoticeResponse qrCodePayNoticeResponse = (QrCodePayNoticeResponse) response.getResult();
        ConvertUtil.convertInput(qrCodePayNoticeResponse);
    }
}
